package org.gap.jseed.threading;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.gap.jseed.injection.BaseInjector;
import org.gap.jseed.injection.ClassWriter;
import org.gap.jseed.injection.JavaSourceUtil;
import org.gap.jseed.threading.annotation.Swing;
import org.gap.jseed.threading.annotation.UIThread;

public class SwingThreadInjector extends BaseInjector {
	
	@Override
	protected Class<? extends Annotation> getAnnotationType() {
		return UIThread.class;
	}

	@Override
	protected void injectMethodWithCode(ClassWriter javaWriter, Method method, Annotation each) {
		UIThread swingUtilities =(UIThread)each;
		Swing action = swingUtilities.action();
		String parameters = getMethodParameters(method);
		String parameterNames = getParameterNames(method.getParameterTypes().length);
		String proxyMethodName = "proxy_" + method.getName();
		javaWriter.addMethod("protected void " + proxyMethodName + "(" + parameters + ") {\n" +
							 "    super." + method.getName() + "(" + parameterNames + ");" +
							 "}");
		String methodBody = JavaSourceUtil.getInvokingMethodCode(proxyMethodName, method.getParameterTypes()) + 
							JavaSourceUtil.callInvokeMethodCode(action.getFieldName(), method.getTypeParameters().length);
		assureFieldIsAdded(javaWriter, action);
		javaWriter.writeBody(method, methodBody);
		javaWriter.ensureReturn(method, false);
	}

	private String getMethodParameters(Method method) {
		String parameters = "";
		int pName = 1;
		for (Class<?> each : method.getParameterTypes()) {
			if (!parameters.isEmpty()) {
				parameters += ", ";
			}
			parameters += each.getSimpleName() + " _" + pName;
		}
		return parameters;
	}

	private String getParameterNames(int parameterLength) {
		String parameters = "";
		for (int pName = 1; pName < parameterLength; pName++) {
			if (!parameters.isEmpty()) {
				parameters += ", ";
			}
			parameters += " _" + pName;
		}
		return parameters;
	}

	private void assureFieldIsAdded(ClassWriter javaWriter, Swing action ) {
		if (!javaWriter.isFieldExisting(action.getFieldName())) {
			javaWriter.addFieldWithDefaultValue(action.getProxyClass(), action.getFieldName(), "new " + action.getProxyClass().getName() + "();");
		}
	}
}
